package com.zlk.algorithm.huawei.leetcode.dp.multidimensional;

import org.junit.Test;

/**
 * @program: algorithm
 * @ClassName Code55_longestCommonSubsequence
 * @description:最长公共子序列
 * 给定两个字符串 text1 和 text2，返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ，返回 0 。
 * 一个字符串的 子序列 是指这样一个新的字符串：它是由原字符串在不改变字符的相对顺序的情况下删除某些字符
 * （也可以不删除任何字符）后组成的新字符串。
 *
 * 例如，"ace" 是 "abcde" 的子序列，但 "aec" 不是 "abcde" 的子序列。
 * 两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
 *
 * 示例 1：
 *
 * 输入：text1 = "abcde", text2 = "ace"
 * 输出：3
 * 解释：最长公共子序列是 "ace" ，它的长度为 3 。
 * 示例 2：
 *
 * 输入：text1 = "abc", text2 = "abc"
 * 输出：3
 * 解释：最长公共子序列是 "abc" ，它的长度为 3 。
 * 示例 3：
 *
 * 输入：text1 = "abc", text2 = "def"
 * 输出：0
 * 解释：两个字符串没有公共子序列，返回 0 。
 * @author: slfang
 * @create: 2025-01-16 14:24
 * @Version 1.0
 **/
public class Code55_longestCommonSubsequence {

    @Test
    public void test(){
        System.out.println(longestCommonSubsequence("bsbininm", "jmjkbkjkv"));
    }

    public int longestCommonSubsequence(String s1, String s2) {
        if(s1.length()<s2.length()){
            String temp = s2;
            s2 = s1;
            s1 = temp;
        }
        int n = s1.length();
        int m = s2.length();
        int[] dp = new int[m+1];
        for (int i = n-1; i >=0 ; i--) {
            int rightDown = 0;
            for (int j = m-1; j >=0 ; j--) {
                int temp = dp[j];
                if(s1.charAt(i)==s2.charAt(j)){
                    dp[j] = rightDown+1;
                }else{
                    dp[j] = Math.max(dp[j],dp[j+1]);
                }
                rightDown = temp;
            }
        }
        return dp[0];
    }

    public int longestCommonSubsequence1(String s1, String s2) {
        int n = s1.length();
        int m = s2.length();
        int[][] dp = new int[n+1][m+1];
        for (int i = n-1; i >=0 ; i--) {
            for (int j = m-1; j >=0 ; j--) {
                if(s1.charAt(i)==s2.charAt(j)){
                    dp[i][j] = dp[i+1][j+1]+1;
                }else{
                    dp[i][j] = Math.max(dp[i+1][j],dp[i][j+1]);
                }
            }
        }
        return dp[0][0];
    }


    public int longestCommonSubsequenceDP(String text1, String text2) {
        //dp[i][j]  o-i范围 0-j范围
        //
        int[][] dp = new int[text1.length()+1][text2.length()+1];
        int n = text1.length();
        int m = text2.length();
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <=m ; j++) {
                dp[i][j] = -1;
            }
        }
        return f(text1,text2,0,0,dp);
    }

    private int f(String s1, String s2, int i, int j,int[][] dp) {
        if(dp[i][j]!=-1){
            return dp[i][j];
        }
        //base case
        if(i==s1.length()||j==s2.length()){
            dp[i][j]=0;
            return 0;
        }
        int ans=0;
        if(s1.charAt(i)==s2.charAt(j)){
            ans  =f(s1,s2,i+1,j+1,dp)+1;
        }else{
            int p2=  f(s1,s2,i+1,j,dp);
            int p3=  f(s1,s2,i,j+1,dp);
            ans = Math.max(p2,p3);
        }
        dp[i][j] = ans;
        return ans;
    }
}
